﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Newtonsoft.Json.Linq;
using Core;
using System.Xml.Serialization;
using System.IO;

namespace Web
{
    public class ReqWrapperMasterDetailBase
    {
        protected T LoadFromXml<T>(string xml, dynamic data = null) {
            XmlSerializer xmlSerializer = new XmlSerializer(typeof(SqlSetting));
            byte[] bytes = System.Text.Encoding.UTF8.GetBytes(xml);
            MemoryStream ms = new MemoryStream(bytes, 0, bytes.Length);
            var sqllSetting = xmlSerializer.Deserialize(ms);
            return (T)sqllSetting;
        }

        //-- format like: 
        // {master:{update:{},insert:{},delete:{}},detail:[{name:'',updated:[{}],inserted:{},deleted:{}},{name:'',update:{},insert:{},delete:{}}]}

        protected JObject _data;
        protected OperateType _operateType;
        public ReqWrapperMasterDetailBase(JObject data, OperateType operateType) {
            _data = data;
            _operateType = operateType;
        }

        public virtual List<ParamBase> ToParams(string xml) {
            var setting = LoadFromXml<SqlSetting>(xml);
            var paramMaster = GetMaster(setting);
            paramMaster.Operator = _operateType;
            var details = GetDetails(setting);
            details.Insert(0, paramMaster);
            return details;
        }

        protected ParamBase GetMaster(SqlSetting setting) {
            ParamBase param = new ReqWrapperBase((JObject)_data["master"], _operateType).ToParam(setting);

            foreach (var child in setting.Children) {
                if (child.Dependency != null && child.Dependency.Count > 0) {
                    child.Dependency.ForEach(x => {
                        x.Value = _data["master"][x.DependencyName] + "";
                    });
                }
            }
            return param;
        }

        protected List<ParamBase> GetDetails(SqlSetting setting) {
            List<ParamBase> paramList = new List<ParamBase>();
            var details = (from x in _data["detail"]
                           select (JObject)x).ToList();

            JArray jArray = null;

            foreach (var sqlSetting in setting.Children) {
                var data = details.FirstOrDefault(x => x["name"] + "" == sqlSetting.JsonName.Trim());
                if (data == null) continue;
                if (data["inserted"] != null && data["inserted"].HasValues) {
                    jArray = data["inserted"] as JArray;
                    PopulateParaList(sqlSetting, paramList, jArray, OperateType.Insert);
                }
                if (data["updated"] != null && data["updated"].HasValues) {
                    jArray = data["updated"] as JArray;
                    PopulateParaList(sqlSetting, paramList, jArray, OperateType.Update);
                }

                if (data["deleted"] != null && data["deleted"].HasValues) {
                    jArray = data["deleted"] as JArray;
                    PopulateParaList(sqlSetting, paramList, jArray, OperateType.Delete);
                }
            }
            return paramList;
        }

        private void PopulateParaList(SqlSetting setting, List<ParamBase> paramList, JArray dataArray, OperateType type) {
            dataArray.ToList().ForEach(x => {
                ParamBase pb = new ParamBase();
                switch (type) {
                    case OperateType.Insert:
                        pb = new ReqWrapperInsert((JObject)x).ToParam(setting);
                        break;
                    case OperateType.Update:
                        pb = new ReqWrapperUpdate((JObject)x).ToParam(setting);
                        break;
                    case OperateType.Delete:
                        pb = new ReqWrapperDelete((JObject)x).ToParam(setting);
                        break;
                    default:
                        break;
                }
                if (setting.Dependency != null && setting.Dependency.Count > 0) {
                    setting.Dependency.ForEach(o => {
                        pb.FieldAlls.FirstOrDefault(m => m.Name == o.Name).Value = o.Value;
                    });
                }
                paramList.Add(pb);
            });
        }
    }
}